import requests
from flask import Flask, jsonify, request, render_template
import pymysql
import bcrypt
import random
import smtplib
import json
from email.mime.text import MIMEText
from email.header import Header
from qiniu import Auth, put_data
import datetime,time
from wechatpayv3 import WeChatPay, WeChatPayType
import os
import dashscope

dashscope.api_key = 'sk-af65048cb8734e409fafdf1a60389ee5'


# 获取脚本所在的目录
script_dir = os.path.dirname(os.path.realpath(__file__))
# 改变当前工作目录到脚本所在的目录
os.chdir(script_dir)

app = Flask(__name__)

# 替换为你的小程序的AppID和AppSecret
APPID = 'wxd67c317d49230f9a'
SECRET = '4994b56436e7b5a979006a4d411fdd05'
WEIXIN_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session"

# 配置七牛云的 Access Key 和 Secret Key
QINIU_ACCESS_KEY = 'rWDDnoIA44V8o8Xd-0QH4OYpWRysDg_Nctby0Se2'
QINIU_SECRET_KEY = 'Va9lJeT3SLfmu9O6HrZYr_e7RMgXSavtXrowxON9'
QINIU_BUCKET_NAME = 'wximgurl'
QINIU_DOMAIN = 'qiniu.aistomatology.cn'  # 七牛云存储空间的外部访问域名
# 创建七牛云的鉴权对象
qiniu_auth = Auth(QINIU_ACCESS_KEY, QINIU_SECRET_KEY)

# 微信支付商户号
MCHID = '1698876990'
# 商户证书私钥
PRIVATE_KEY = open('./apiclient_key.pem').read()
# 商户证书序列号
CERT_SERIAL_NO = '634BFA31D42D4245A782AF4B1ADB0998DDF6E5F6'
# API v3密钥， https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
APIV3_KEY = 'TZJzzRSYCGnKwhsJ8nP4EsAzePWyaJPA'
NOTIFY_URL = 'https://www.aistomatology.cn/wx/payBack'
# 微信支付平台证书缓存目录
CERT_DIR = './cert'

wxpay = WeChatPay(
    wechatpay_type=WeChatPayType.MINIPROG,
    mchid=MCHID,
    private_key=PRIVATE_KEY,
    cert_serial_no=CERT_SERIAL_NO,
    apiv3_key=APIV3_KEY,
    appid=APPID,
    notify_url=NOTIFY_URL,
    cert_dir=CERT_DIR)


def createNoncestr(length=16):
    """产生随机字符串，不长于32位"""
    chars = "abcdefghijklmnopqrstuvwxyz0123456789"
    strs = []
    for x in range(length):
        strs.append(chars[random.randrange(0, len(chars))])
    return "".join(strs)

def generate_order_number():
    # 获取当前的时间戳
    timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    # 生成一个4位数的随机流水号
    random_number = random.randint(1000, 9999)
    # 生成订单号
    order_id = f"ZC{timestamp}{random_number:04d}"
    return order_id

@app.route('/')
def index():
    return render_template('logflase.html', title='Welcome Page', name='John Doe')

@app.route('/firstpage')
def firstpage():
    return render_template('flask1.html')

@app.route('/log', methods=['POST'])
def log():
    log = False;
    name = request.form.get('name')
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    db = 'user_info'
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    # 只要不涉及数据的更改，可以不需要调用commit()方法提交更改
    result = cursor.fetchall()
    FInalname = "empty"
    FInalemail = "empty"
    for row in result:
        if (row['name'] == name):
            FInalname = name
            FInalemail = row['age']
            log = True
            break

    cursor.close()
    conn.close()
    return render_template('logging.html', statu=log)
    # return render_template('flask1.html', title=FInalemail, name=FInalname)


@app.route('/enroll', methods=['GET'])
def enroll():
    ac = request.args.get('account')
    psw = request.args.get('pasw')
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    db = 'user_info'
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    # 插入数据
    sql = f"INSERT INTO {db} (accout, pasw) VALUES (ac, pasw)"
    cursor.execute(sql)
    conn.commit()


@app.route('/wx/login', methods=['GET'])
def wx_login():
    code = request.args.get('code')  # 获取小程序端传递过来的code
    if not code:
        return jsonify({'error': 'Missing code parameter'}), 400

    data = {
        'appid': APPID,
        'secret': SECRET,
        'js_code': code,
        'grant_type': 'authorization_code'
    }

    response = requests.get(WEIXIN_LOGIN_URL, params=data)
    if response.status_code == 200:
        result = response.json()
        openid = result.get('openid')  # 获取用户的OpenID
        session_key = result.get('session_key')  # 可选，获取会话密钥
        unionid = result.get('unionid')  # 可选，当用户已经绑定微信开放平台账号时，会返回此字段

        # 可以将openid等数据返回给小程序端或存储在服务器端
        return jsonify({'openid': openid, 'unionid': unionid})
    else:
        return jsonify({'error': 'Failed to get openid from WeChat'}), 500


@app.route('/andorid/sendmail', methods=['GET'])
def sendmail():
    mail = request.args.get('mail')  # 获取小程序端传递过来的code
    smtp_obj = smtplib.SMTP_SSL("smtp.qq.com", 465)
    smtp_obj.login("2153549054@qq.com", "jqngwxhvkpnnecib")
    # 设置邮件头
    random_number = random.randint(1000, 9999)
    mail_text = f"验证码为：{random_number}"
    msg = MIMEText(mail_text, 'plain', "utf-8")
    msg["From"] = "2153549054@qq.com"
    msg["To"] = Header("用户", "utf-8")
    msg["Subject"] = Header("导诊服务验证码通知", "utf-8")
    # 发送
    smtp_obj.sendmail("2153549054@qq.com", [mail], msg.as_string())
    return jsonify({'identycode': random_number})


@app.route('/andorid/enroll', methods=['POST'])
def androidenroll():
    # 注册
    isExiteAc = False
    ac = request.form.get('mail')
    psw = request.form.get('pasw')
    # hash加密
    salt = bcrypt.gensalt()
    psw = bcrypt.hashpw(psw.encode(), salt)

    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    db = 'user_info'
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    result = cursor.fetchall()
    for row in result:
        if (row['accout'] == ac):
            isExiteAc = True
            break
    if (isExiteAc):
        print("账户已存在")
        return jsonify({'isExiteAc': 0})
        cursor.close()
        conn.close()
    else:
        sql = f"INSERT INTO {db} (accout, pasw) VALUES (%s, %s)"
        values = (ac, psw)
        cursor.execute(sql, values)
        conn.commit()
        cursor.close()
        conn.close()
        return jsonify({'isExiteAc': 1})


@app.route('/andorid/log', methods=['POST'])
def androidlog():
    logissuc = False
    ac = request.form.get('mail')
    psw = request.form.get('pasw')
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    db = 'user_info'
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    result = cursor.fetchall()
    for row in result:
        if (row['accout'] == ac and bcrypt.checkpw(psw.encode('utf-8'), row['pasw'].encode('utf-8'))):
            logissuc = True
            break

    if logissuc:
        cursor.close()
        conn.close()
        return jsonify({'logstatus': 1,'detail':'登录成功'})

    else:
        sql = f"INSERT INTO {db} (accout, pasw) VALUES (%s, %s)"
        values = (ac, psw)
        cursor.execute(sql, values)
        conn.commit()
        cursor.close()
        conn.close()
        return jsonify({'logstatus': 1,'detail':'账户创建，登录成功'})


# 向用户发送检测通知并存储数据
@app.route('/wx/sendmessage', methods=['POST'])
def send_subscribe_message():
    code = request.form.get('code')  # 获取小程序端传递过来的code
    student_name = request.form.get('name')  # 学生姓名
    test_result = request.form.get('message')  # 检测结果
    capture_time = request.form.get('time')  # 拍摄时间
    result2 = request.form.get('result')  # 检测结果 是一个二维数组
    imgurl = request.form.get('imgurl')  # 保存图像的地址
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    db = 'wx_user_id'  # 要查询的数据表
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    result = cursor.fetchall()
    isexte = False  # 记录是否存在openid,false为不存在
    diasenum = 0  # 记录疾病数量，默认为新用户，检测了一条
    for row in result:
        if (row['openid'] == code):
            diasenum += row['nums']
            isexte = True
            break
    if (isexte == False):
        # 插入openid
        sql = f"INSERT INTO wx_user_id (openid,nums) VALUES ('{code}', {diasenum})"
        cursor.execute(sql)
        conn.commit()
    # 数据库加一
    sql = f"UPDATE wx_user_id SET nums = {diasenum + 1} WHERE openid = '{code}'"
    cursor.execute(sql)
    conn.commit()
    # 主表： openid num
    # 外键表：openid result diseaseId

    sql = f"INSERT INTO wx_disasesdata (useropenid,disases,data,imgurl) VALUES ('{code}', '{result2}','{capture_time}','{imgurl}')"
    cursor.execute(sql)
    conn.commit()
    # todo 获取主表的num作为diseaseId，存入openid result diseaseId

    # 关闭数据
    cursor.close()
    conn.close()

    openid = code
    template_id = '-WTRz9G1fH_LYOC4L90i41H6DXhQ-YfsE4YNCuWe50Q'
    page = 'pages/toothExam/toothExam'
    # 获取 access token
    url = f"https://api.weixin.qq.com/cgi-bin/token?appid={APPID}&secret={SECRET}&grant_type=client_credential"
    response2 = requests.get(url)
    data = response2.json()
    access_token = data['access_token']

    # 准备消息内容
    message_data = {
        "touser": openid,  # 用户 OpenID
        "template_id": template_id,
        "page": page,
        "miniprogram_state": "developer",
        "data": {
            "phrase10": {
                "value": test_result  # 检测结果
            },
            "thing20": {
                "value": student_name  # 学生姓名
            },
            "time25": {
                "value": capture_time  # 拍摄时间
            }
        }
    }

    json_bytes = json.dumps(message_data).encode('utf-8')

    # 发送订阅消息
    url = f"https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={access_token}"
    requests.post(url, data=json_bytes)
    return jsonify(0), 200


# 用户点击跳转的页面后进入查询，获取其所有病例
@app.route('/wx/getuserDisase', methods=['POST'])
def getuserDisase():
    code = request.form.get('code')  # 获取小程序端传递过来的code
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    db = 'wx_disasesdata'
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    # 只要不涉及数据的更改，可以不需要调用commit()方法提交更改useropenid,disases
    result = cursor.fetchall()
    ans = []
    for row in result:
        if (row['useropenid'] == code):
            if (row['disases'] != None):
                add = eval(row['disases'])
                ans.append({'content': add, 'data': row['data'], 'imgurl': row['imgurl']})
            else:
                ans.append({'content': [], 'data': row['data'], 'imgurl': row['imgurl']})

    cursor.close()
    conn.close()
    return jsonify({'disases': ans}), 200


# 上传图像到七牛云并获取imgurl地址 目前仅为http
@app.route('/returnImgUrl', methods=['POST'])
def upload_file():
    # 确保文件已包含在请求中
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']
    # 如果用户没有选择文件，浏览器可能会提交一个没有文件名的空部分
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400
    if file:
        # 获取文件的二进制数据
        file_data = file.read()
        # 生成上传文件的唯一文件名，你可以根据需要自定义文件名生成逻辑
        file_name = file.filename
        # 使用鉴权对象生成上传令牌
        token = qiniu_auth.upload_token(QINIU_BUCKET_NAME)
        print(token)

        ret, err = put_data(token, file_name, file_data)
        if ret['key'] is not None:
            # 文件上传成功，获取文件的完整 URL
            file_url = f'http://{QINIU_DOMAIN}/{ret["key"]}'
            return jsonify({'message': 'File uploaded successfully', 'file_url': file_url}), 200
        return jsonify(0), 200


# 返回医院科室的信息
@app.route('/returnDocotor', methods=['POST'])
def returnDocotor():
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    # todo 还未加入医生筛选工作
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    db = 'doctor_table'
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    result = cursor.fetchall()
    shuzu = []
    for row in result:
        shuzu.append({'department':row['department'], 'doctor_id':row['docotor_id'], 'name':row['name']})
    cursor.close()
    conn.close()
    return jsonify({'doctors': shuzu}), 200
p=0
@app.route('/havenew', methods=['POST'])
def returnnew():
    global p
    data=p
    if(data==1):
        p=0
    return jsonify({'isSuc': data}), 200

# 接收医生id，实现挂号
@app.route('/Registered', methods=['POST'])
def Registered():
    global p
    ac = request.form.get('account')
    doc = request.form.get('doctor')
    doc_name=request.form.get('doctorName')
    department = request.form.get('depart')
    time = request.form.get('time')
    #更新获取状态

    p=1

    user_phone=request.form.get('userPhone')
    user_name=request.form.get('userName')
    user_id=request.form.get('IDCard')
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    # todo 还未加入医生筛选工作
    regSuc=True
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据

    db = 'appointment'
    order_number = generate_order_number()
    sql = f"INSERT INTO {db} (success, user_id,doctor_id,time,order_num,doctor_name,user_phone,department,user_name,user_idcard) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
    values = (0, ac, doc, time,order_number,doc_name,user_phone,department,user_name,user_id)
    cursor.execute(sql, values)

    db = 'doctor_table'
    sql1 = f"UPDATE {db} SET wait_num = wait_num+1 WHERE docotor_id = {doc}"
    cursor.execute(sql1)

    conn.commit()

    cursor.close()
    conn.close()
    return jsonify({'isSuc': 1, 'detail': '挂号成功','order':order_number}), 200


# 提供给医生的调用接口
@app.route('/doctorFix', methods=['POST'])
def doctorFix():
    # 提供就诊记录的id
    data = request.get_json()

    # 从 JSON 数据中提取 'id'
    id = data.get('id')
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    # 就诊记录更新
    db = 'appointment'
    sql = f"UPDATE {db} SET success = 1 WHERE order_num = %s"
    values = (id)
    cursor.execute(sql, values)
    conn.commit()
    cursor.close()
    conn.close()
    return jsonify({'isSuc': 1, 'detail': '就诊记录已修改'}), 200

#取消挂号
@app.route('/CancelRegister', methods=['POST'])
def CancelReg():
    order=request.form.get('order')
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    db = 'appointment'
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    try:
        sql = f"DELETE FROM {db} WHERE order_num = %s"
        cursor.execute(sql,order)
        if cursor.rowcount == 0:
            print(f"No rows affected for order_num: {order}.")
            return jsonify({'isSuc': 0, 'detail': '取消挂号失败，不存在订单号'}), 500
        else:
            conn.commit()
            return jsonify({'isSuc': 1, 'detail': '取消挂号成功'}), 200
    finally:
        cursor.close()
        conn.close()

#根据用户id 返回用户的订单号
@app.route('/ReturnRegister', methods=['POST'])
def ReturnReg():
    account = request.form.get('account')
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    db = 'appointment'
    nums=[]
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    try:
        sql = f"SELECT * FROM {db} WHERE  user_id = %s"
        cursor.execute(sql,account)
        if cursor.rowcount == 0:
            return jsonify({'isSuc': 0, 'detail': '用户不存在任何订单号'}), 500
        else:
            result = cursor.fetchall()
            for row in result:
                nums.append(row)
            return jsonify({'isSuc': 1, 'detail': '返回订单号成功','nums':nums}), 200
    finally:
        cursor.close()
        conn.close()

@app.route('/RecommendDepart', methods=['POST'])
def RecommendDepart():
    numbers = ['哮喘','流感','肺结核','糖尿病','抑郁症','焦虑症','失眠症','肥胖症','高脂血症','关节炎','骨质疏松症']

    # 如果列表长度小于4，可以多次使用random.choice()来抽取
    if len(numbers) >= 4:
        selected_numbers = random.sample(numbers, 4)
    else:
        selected_numbers = random.sample(numbers, len(numbers))
    return jsonify({'isSuc': 1, 'detail': '返回推荐科室成功', 'nums':selected_numbers}), 200

#医生端返回挂号信息
@app.route('/Doctor', methods=['POST'])
def doc():
    conn = pymysql.Connect(
        host="121.196.247.129",
        user="hospital",
        password="xz4XmwLkaxkaM6Dd",
        database="hospital",
        port=3306,  # 端口号，默认即3306
        charset="utf8"
    )
    db = 'appointment'
    nums = []
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 以字典的形式取数据
    sql = f"SELECT * FROM {db}"
    cursor.execute(sql)
    result = cursor.fetchall()
    for row in result:
        nums.append(row)
    cursor.close()
    conn.close()
    return jsonify({'isSuc': 1, 'detail': '返回订单号成功', 'nums': nums}), 200

@app.route('/wx/getPayParams', methods=['POST'])
def wxorder():
    openid = request.form.get('code')  # 获取小程序端传递过来的code
    payer = {'openid': openid}
    amout=1
    trade_no=generate_order_number()#随机订单号。商户号下唯一存在，自己生成
    code, message = wxpay.pay(
        description='齿豆充值',
        out_trade_no=trade_no,
        amount={'total': amout},
        pay_type=WeChatPayType.JSAPI,
        payer=payer
    )
    json_object = json.loads(message)
    if(code==200):
       prepay_id = json_object["prepay_id"]
       appId=APPID
       timeStamp= str(int(time.time()))
       nonceStr=createNoncestr(length=32)
       package='prepay_id='+prepay_id
       sign = wxpay.sign([APPID, timeStamp, nonceStr, package])
       signtype = 'RSA'
       return jsonify({'isSuc': 1, 'detail':'拉取preid成功','payParams':{
           'appId': appId,
           'timeStamp':timeStamp,
           'nonceStr': nonceStr,
           'package': 'prepay_id=%s' % prepay_id,
           'signType': signtype,
           'paySign': sign,
       }}), 200
    else:
      return jsonify({'isSuc': 0, 'detail': '拉取preid失败', 'payParams': message}), 200

@app.route('/wx/payBack', methods=['POST'])
def payback():

    return 'success'

@app.route('/wx/AiCommute',methods=['POST'])
def AiCommute():
    usercontent = request.form.get('content')  # 获取小程序端传递过来的code
    messages = [{'role': 'user', 'content': usercontent}]

    response = dashscope.Generation.call(dashscope.Generation.Models.qwen_turbo, messages=messages,
                                         result_format='message')

    return jsonify({'isSuc': 0, 'detail': response}), 200

@app.route('/wx/nativepay',methods=['GET'])
def nativepay():
    out_trade_no = generate_order_number()#随机订单号。商户号下唯一存在，自己生成
    description = '支付测试'
    amount = 1
    code, message = wxpay.pay(
        description=description,
        out_trade_no=out_trade_no,
        amount={'total': amount},
        pay_type=WeChatPayType.NATIVE
    )
    return jsonify({'code': code, 'message': message})
if __name__ == '__main__':
    app.run(host='172.20.97.170', port=7560)

